package xxl.robotlegs.extensions.viewprocessormap.impl 
{
	import flash.display.DisplayObject;
	import flash.utils.Dictionary;
	import xxl.robotlegs.extensions.matching.impl.TypeMatcher;
	import xxl.robotlegs.extensions.viewprocessormap.api.IViewProcessorFactory;
	import xxl.robotlegs.extensions.viewprocessormap.api.IViewProcessorUnmapper;
	import xxl.robotlegs.extensions.matching.api.ITypeMatcher;
	import xxl.robotlegs.extensions.viewmanager.api.IViewHandler;
	import xxl.robotlegs.extensions.viewprocessormap.api.IViewProcessorMap;
	import xxl.robotlegs.extensions.viewprocessormap.api.IViewProcessorMapper;
	import xxl.robotlegs.extensions.viewprocessormap.api.IViewProcessorViewHandler;
	/**
	 * ...
	 * @author XXL
	 */
	public class ViewProcessorMap implements IViewProcessorMap, IViewHandler
	{
		private const _mappers:Dictionary = new Dictionary();
		private var _handler:IViewProcessorViewHandler;
		private const NULL_UNMAPPER:IViewProcessorUnmapper = new NullViewProcessorUnmapper();
		
		public function ViewProcessorMap(factory:IViewProcessorFactory, handler:IViewProcessorViewHandler = null)
		{
			_handler = handler || new ViewProcessorViewHandler(factory);
		}
		
		private function createMapper(matcher:ITypeMatcher):IViewProcessorMapper
		{
			return new ViewProcessorMapper(matcher.createTypeFilter(), _handler);
		}
		
		/* INTERFACE xxl.robotlegs.extensions.viewprocessormap.api.IViewProcessorMap */
		
		public function mapMatcher(matcher:ITypeMatcher):IViewProcessorMapper 
		{
			return _mappers[matcher.createTypeFilter().descriptor] ||= createMapper(matcher);
		}
		
		public function map(type:Class):IViewProcessorMapper 
		{
			const matcher:ITypeMatcher = new TypeMatcher().allOf(type);
			return mapMatcher(matcher);
		}
		
		public function unmapMatcher(matcher:ITypeMatcher):IViewProcessorUnmapper 
		{
			return _mappers[matcher.createTypeFilter().descriptor] || NULL_UNMAPPER;
		}
		
		public function unmap(type:Class):IViewProcessorUnmapper 
		{
			const matcher:ITypeMatcher = new TypeMatcher().allOf(type);
			return unmapMatcher(matcher);
		}
		
		public function process(item:Object):void 
		{
			const type:Class = item["constructor"];
			_handler.processItem(item, type);
		}
		
		public function unprocess(item:Object):void 
		{
			const type:Class = item["constructor"];
			_handler.unprocessItem(item, type);
		}
		
		/* INTERFACE xxl.robotlegs.extensions.viewmanager.api.IViewHandler */
		
		public function handleView(view:DisplayObject, type:Class):void 
		{
			_handler.processItem(view, type);
		}
		
	}

}